public class Tester2 extends TestToolBox {

	private Sorter sorter;
	private double preSortLow;
	private double preSortHi;
	private int preSortIntSteps;
	private int[] stepArray;
	private double[] preSortInterval;
	private int[] array;
	private int[] scrambledArray;

	public Tester2(int first, int last, int reps, int steps, Sorter quicksort,
			double low, double hi, int num) {
		super(first, last, reps, steps);
		this.sorter = quicksort;
		this.preSortIntSteps = num;
		this.preSortHi = hi;
		this.preSortLow = low;

	}

	public double[] getPreSortInterval() {
		return preSortInterval;
	}

	public double[][] test() {
		testSetup();
		double[][] runtimes = new double[preSortInterval.length][stepArray.length - 1];
		int[] arrayCopy;
		double startTime;
		double runTime;

		for (int i = 0; i < preSortInterval.length; i++) {

			preSortArray(array, preSortInterval[i]);
			for (int j = 0; j < reps; j++) {
				for (int k = 1; k <= steps; k++) {
					arrayCopy = copyArrayFromIndex1ToIndex2(array,
							stepArray[0], stepArray[k]);
					System.gc();
					startTime = System.nanoTime();
					sorter.sort(arrayCopy, arrayCopy.length - 1);
					runTime = (System.nanoTime() - startTime);
					// add each new finishtime, the average will be calculated
					// later
					runtimes[i][k - 1] = ((runtimes[i][k - 1] + runTime));
				}
			}
			for (int k = 0; k < stepArray.length - 1; k++) {
				runtimes[i][k] = runtimes[i][k] / reps / 1000;
			}
			array = populateArray(first, last);
		}
		return runtimes;
	}

	private void testSetup() {
		stepArray = makeStepArray();
		makePreSortIntervals();
		array = populateArray(first, last);
		scrambledArray = copyArrayFromIndex1ToIndex2(array, first, last + 1);
		scrambledArray = randomizeArray(scrambledArray);
	}

	public int[] getStepArray() {
		return stepArray;
	}

	private void preSortArray(int[] array, double preSortDeg) {

		int index1;
		int index2;
		int tmp;
		int scrambledCopyLen = scrambledArray.length;
		int numToPresort = (int) (scrambledCopyLen * (1 - preSortDeg));
		int halfInterval = (int) Math.ceil(numToPresort / 2.0);
		for (int i = 0; i < halfInterval; i++) {
			index1 = scrambledArray[(scrambledCopyLen - 1) - i];
			index2 = scrambledArray[i];
			tmp = array[index1];
			array[index1] = array[index2];
			array[index2] = tmp;
		}
	}

	private int[] copyArrayFromIndex1ToIndex2(int[] array, int fromIndex,
			int toIndex) {
		int copySize = (int) Math.ceil(toIndex - fromIndex);
		int[] copy = new int[copySize];
		for (int i = 0; i < copySize; i++) {
			copy[i] = array[fromIndex + i];
		}
		return copy;
	}

	private void makePreSortIntervals() {
		double stepSize = (preSortHi - preSortLow) / preSortIntSteps;
		preSortInterval = new double[preSortIntSteps + 1];
		preSortInterval[0] = preSortLow;
		for (int i = 1; i <= preSortIntSteps; i++) {
			preSortInterval[i] = preSortInterval[i - 1] + stepSize;
		}
	}
}
